﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Text;
using System.Reflection;
using System.Xml.Linq;

namespace TomVanGaever.BCS.Parser
{
    public class BCSParser : IBCSParser
    {
        private List<PropertyInfo> m_properties;
        private IEnumerable<PropertyInfo> m_propertyfilter;
        public IEnumerable<PropertyInfo> Properties { get { return m_properties; } }

        private XDocument m_model;
        private XElement m_lobsystems;
        private XNamespace m_ns;
        private Type m_type;
        private Type m_serviceClass;
        private PropertyInfo m_identifier;

        private string m_classFullName;
        private string m_serviceClassFullName;
        private string m_typecollection;
        private string m_lobname;

        private string m_readListName = "ReadList";
        private string m_readItemName = "ReadItem";
        private string m_createName = "Create";
        private string m_updateName = "Update";
        private string m_deleteName = "Delete";
        private string m_returnParameterName = "returnParameter";
        private string m_newParameterName = "newParameter";

        private string m_idTypecollection;
        private string m_idCollection = "Idcollection";
        private string m_idEnumeratorName = "IDEnumeratorInstance";

        public bool IsFilterCapabilitiesEnabled { get; set; }
        public bool IsCreateCapabilitiesActivitated { get; set; }
        public bool IsSearchCapabilitiesActivitated { get; set; }
        public bool IsUpdateCapabilitiesActivitated { get; set; }
        public bool IsDeleteCapabilitiesActivitated { get; set; }

        public BCSParser()
        {
        }

        public void Load(Type type, Type ServiceClass, PropertyInfo Identifier, IEnumerable<PropertyInfo> propertyfilter)
        {
            //Load parameters
            this.m_lobname = GetLobsystemName(type);
            this.m_type = type;
            this.m_serviceClass = ServiceClass;
            this.m_identifier = Identifier;
            this.m_propertyfilter = propertyfilter;

            //Service Class FullName
            this.m_serviceClassFullName = ServiceClass.Namespace + "." + ServiceClass.Name + ", " + m_lobname;
            this.m_classFullName = ServiceClass.Namespace + "." + type.Name + ", " + m_lobname;
            this.m_typecollection = "System.Collections.Generic.IEnumerable`1[[" + m_classFullName + "]]";
            this.m_idTypecollection = "System.Collections.Generic.IEnumerable`1[[" + m_identifier.PropertyType.FullName + "]]";

            //prepare type properties
            this.m_properties = type.GetProperties().ToList();

            //prepare BDCM XML Namespace

            //prepare Lobsystems
            m_ns = XNamespace.Get(BCSConstants.BUSINESSDATACATALOGSCHEMANAMESPACE);
            m_lobsystems = new XElement(m_ns + BCSConstants.LOBSYSTEMS,
                new XElement(m_ns + BCSConstants.LOBSYSTEM,
                    new XAttribute(BCSConstants.LOBSYSTEMTYPE, BCSConstants.LOBSYSTEMTYPEVALUE),
                    new XAttribute(BCSConstants.NAME, m_lobname),

                    //Begin Properties
                    new XElement(m_ns + BCSConstants.PROPERTIES,
                        new XElement(m_ns + BCSConstants.PROPERTY,
                            new XAttribute(BCSConstants.NAME, BCSConstants.SHOWINSEARCHUI),
                            new XAttribute(BCSConstants.TYPE, typeof(string).FullName),
                            true
                            )
                        ),

                    //LobSystemInstances
                    new XElement(m_ns + BCSConstants.LOBSYSTEMINSTANCES,

                        //LobSystemInstance
                        new XElement(m_ns + BCSConstants.LOBSYSTEMINSTANCE,
                            new XAttribute(BCSConstants.NAME, m_lobname),

                            //LobSystemInstance properties
                            new XElement(m_ns + BCSConstants.PROPERTIES,
                                new XElement(m_ns + BCSConstants.PROPERTY,
                                    new XAttribute(BCSConstants.NAME, BCSConstants.SHOWINSEARCHUI),
                                    new XAttribute(BCSConstants.TYPE, typeof(string).FullName),
                                    true
                                    )
                                )
                            )
                        ),

                    //Entities
                    new XElement(m_ns + BCSConstants.ENTITIES,
                //Entity
                        new XElement(m_ns + BCSConstants.ENTITY,
                            new XAttribute(BCSConstants.NAME, type.Name),
                            new XAttribute(BCSConstants.NAMESPACE, type.Namespace),
                            new XAttribute(BCSConstants.VERSION, new Version("1.0.0.0")),
                            new XAttribute(BCSConstants.ESTIMATEDINSTANCECOUNT, "1000"),
                //Entity properties
                            new XElement(m_ns + BCSConstants.PROPERTIES,
                                new XElement(m_ns + BCSConstants.PROPERTY,
                                    new XAttribute(BCSConstants.NAME, BCSConstants.CLASS),
                                    new XAttribute(BCSConstants.TYPE, typeof(string).FullName),
                                    m_serviceClassFullName
                                    ),
                                new XElement(m_ns + BCSConstants.PROPERTY,
                                    new XAttribute(BCSConstants.NAME, BCSConstants.SHOWINSEARCHUI),
                                    new XAttribute(BCSConstants.TYPE, typeof(string).FullName),
                                    true
                                )
                            ),
                //Entity Identifiers
                            new XElement(m_ns + BCSConstants.IDENTIFIERS,
                                new XElement(m_ns + BCSConstants.IDENTIFIER,
                                    new XAttribute(BCSConstants.NAME, m_identifier.Name),
                                    new XAttribute(BCSConstants.TYPENAME, m_identifier.PropertyType.FullName)
                                    )
                            ),
                                //Entity Methods
                                new XElement(m_ns + BCSConstants.METHODS,

                                    //ReadList
                                    new XComment("start finder method"),
                                    BuildFinderMethod(this.IsFilterCapabilitiesEnabled),
                                    new XComment("end finder method"),

                                    //ReadItem
                                    new XComment("start specificfinder method"),
                                    GetSpecificFinderMethod(),
                                    new XComment("end specificfinder method"),

                                    //GetIdCollection
                                    new XComment("start IDEnumerator method"),
                                    IsSearchCapabilitiesActivitated ? GetIDEnumerator(): null,
                                    new XComment("end IDEnumerator method"),

                                    //BuiltCreateMethod
                                    new XComment("start create method"),
                                    IsCreateCapabilitiesActivitated? GetCreateMethod() : null,
                                    new XComment("end create method"),

                                    //BuiltUpdatesMethod
                                    new XComment("start update method"),
                                    IsUpdateCapabilitiesActivitated ? GetUpdateMethod() : null,
                                    new XComment("end update method"),

                                    //BuiltDeleteMethod
                                    new XComment("start delete method"),
                                    IsDeleteCapabilitiesActivitated ? GetDeleteMethod() : null,
                                    new XComment("end delete method")
                            )
                        )
                    )
                )
            );

            //Build the model and add the created lobsystems
            m_model = new XDocument(
                new XComment("Generated by BCSParser at " + DateTime.Now.ToString()),
                new XElement(m_ns + "Model",
                    new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
                    new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema"),
                    new XAttribute("Name", m_lobname),
                    m_lobsystems
                    )
                );
        }

        private string GetLobsystemName(Type type)
        {
            string[] tmp = type.Namespace.Split('.');
            return tmp[tmp.Length - 1];
        }

        public void Save(string location)
        {
            m_model.Save(location);
        }

        public void SetVersion(Version version)
        {
            m_model.Element(m_ns + "Model").Element(m_ns + "LobSystems").Element(m_ns + "LobSystem").Element(m_ns + "Entities").Element(m_ns + "Entity").Attribute("Version").Value = version.ToString(4);
        }

        public static Version GetVersion(string previousBDCMLocation)
        {
            var doc = XDocument.Load(previousBDCMLocation);
            var ns = doc.Elements().First().GetDefaultNamespace();
            XElement model = doc.Element(ns + "Model");
            Version version = new Version(model.Element(ns + "LobSystems").Element(ns + "LobSystem").Element(ns + "Entities").Element(ns + "Entity").Attribute("Version").Value);
            return version;
        }

        private XElement BuildFinderMethod()
        {
            XElement findermethod = new XElement(
                m_ns + BCSConstants.METHOD,
                new XAttribute(BCSConstants.NAME, m_readListName),

                //PARAMETERS
                new XElement(m_ns + BCSConstants.PARAMETERS,

                    //RETURN PARAMETER
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.NAME, m_returnParameterName),
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.Return),

                        //TYPEDESCRIPTOR
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_typecollection),
                            new XAttribute(BCSConstants.ISCOLLECTION, true),
                            new XAttribute(BCSConstants.NAME, m_type.Name + "List"),

                                //TYPEDESCRIPTORS
                                new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS,
                                    new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                                        new XAttribute(BCSConstants.NAME, m_type.Name),
                                        new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                                        GetTypeDescriptorFromTypeProperties()
                                    )
                                )
                            )
                        )
                ),
                //METHODINSTANCES
                new XElement(m_ns + BCSConstants.METHODINSTANCES,
                //METHODINSTANCE
                    GetFinderMethodInstance(BCSConstants.MethodType.Finder, m_readListName, m_type.Name + " List", true)
                )
            );
            return findermethod;
        }

        private XElement BuildFinderMethod(bool enableFilterCapabilities)
        {
            XElement filterDescriptors = null;
            XElement filterTypeDescriptor = null;
            if (enableFilterCapabilities)
            {
                filterDescriptors = BuildFinderMethodFilterDescriptor("DescriptionFilter", "Filter by description");
                filterTypeDescriptor = BuildFinderMethodFilterTypeDescriptor("DescriptionFilterValue", "Description", "DescriptionFilterValueTypeDescriptor", "DescriptionFilter");
            }

            XElement findermethod = new XElement(
                    m_ns + BCSConstants.METHOD,
                    new XAttribute(BCSConstants.NAME, m_readListName),

                    //FILTER DESCRIPTORS IF NEEDED
                    filterDescriptors,

                    //PARAMETERS
                    new XElement(m_ns + BCSConstants.PARAMETERS,

                        //RETURN PARAMETER
                        new XElement(m_ns + BCSConstants.PARAMETER,
                            new XAttribute(BCSConstants.NAME, m_returnParameterName),
                            new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.Return),

                            //TYPEDESCRIPTOR
                            new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                                new XAttribute(BCSConstants.TYPENAME, m_typecollection),
                                new XAttribute(BCSConstants.ISCOLLECTION, true),
                                new XAttribute(BCSConstants.NAME, m_type.Name + "List"),

                                    //TYPEDESCRIPTORS
                                    new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS,
                                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                                            new XAttribute(BCSConstants.NAME, m_type.Name),
                                            new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                                            GetTypeDescriptorFromTypeProperties()
                                        )
                                    )
                                )
                            ),
                //FILTER PARAMATER
                        filterTypeDescriptor
                    ),
                //METHODINSTANCES
                    new XElement(m_ns + BCSConstants.METHODINSTANCES,
                //METHODINSTANCE
                        GetFinderMethodInstance(BCSConstants.MethodType.Finder, m_readListName, m_type.Name + " List", true)
                    )
                );
            return findermethod;
        }

        private XElement BuildFinderMethodFilterDescriptor(string name, string defaultDisplayName)
        {
            XElement filterDescriptors = new XElement(m_ns + BCSConstants.FILTERDESCRIPTORS,
                new XElement(m_ns + BCSConstants.FILTERDESCRIPTOR,
                    new XAttribute(BCSConstants.NAME, name),
                    new XAttribute(BCSConstants.TYPE, BCSConstants.FILTERTYPE.Wildcard),
                    new XAttribute(BCSConstants.DEFAULTDISPLAYNAME, defaultDisplayName)
                )
            );
            //<FilterDescriptor Name="DescriptionFilter" Type="Wildcard" DefaultDisplayName="Filter by description" />
            return filterDescriptors;
        }

        private XElement BuildFinderMethodFilterTypeDescriptor(string name, string defaultDisplayName, string DescriptionFilterdescriptorname, string associatedfilter)
        {
            XElement element = new XElement(m_ns + BCSConstants.PARAMETER,
                new XAttribute(BCSConstants.NAME, name),
                new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.In),
                new XAttribute(BCSConstants.DEFAULTDISPLAYNAME, defaultDisplayName),
                new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                    new XAttribute(BCSConstants.NAME, DescriptionFilterdescriptorname),
                    new XAttribute(BCSConstants.TYPENAME, typeof(string).FullName),
                    new XAttribute(BCSConstants.ASSOCIATEDFILTER, associatedfilter)
                )
           );
            //<Parameter Name="DescriptionFilterValue" Direction="In" DefaultDisplayName="Description">
            //       <TypeDescriptor Name="DescriptionFilterValueTypeDescriptor" TypeName="System.String" AssociatedFilter="DescriptionFilter" /></Parameter>
            //   </Parameters>
            return element;
        }


        private XElement GetSpecificFinderMethod()
        {
            XElement specificfindermethod = new XElement(
                m_ns + BCSConstants.METHOD,
                new XAttribute(BCSConstants.NAME, m_readItemName),
                //PARAMETERS
                new XElement(m_ns + BCSConstants.PARAMETERS,

                    //PARAMETER IN
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.In),
                        new XAttribute(BCSConstants.NAME, m_identifier.Name),
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_identifier.PropertyType.FullName),
                            new XAttribute(BCSConstants.IDENTIFIERNAME, m_identifier.Name),
                            new XAttribute(BCSConstants.NAME, m_identifier.Name)
                        )
                    ),

                    //PARAMETER OUT
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.Return),
                        new XAttribute(BCSConstants.NAME, m_returnParameterName),
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.NAME, m_type.Name),
                            new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                            GetTypeDescriptorFromTypeProperties()
                        )
                    )
                ),
                //METHODINSTANCES
                new XElement(m_ns + BCSConstants.METHODINSTANCES,
                    GetFinderMethodInstance(BCSConstants.MethodType.SpecificFinder, m_readItemName, "Read " + m_type.Name, true)
                    )
            );
            return specificfindermethod;
        }

        private XElement GetIDEnumerator()
        {
            XElement idEnumerator = new XElement(
                m_ns + BCSConstants.METHOD,
                new XAttribute(BCSConstants.NAME, "GetIdCollection"),
                //PARAMETERS
                new XElement(m_ns + BCSConstants.PARAMETERS,

                    //RETURN PARAMETER
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.NAME, m_returnParameterName),
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.Return),

                        //TYPEDESCRIPTOR
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_idTypecollection),
                            new XAttribute(BCSConstants.ISCOLLECTION, true),
                            new XAttribute(BCSConstants.NAME, m_idCollection),

                                //TYPEDESCRIPTORS
                                new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS,
                                    new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                                        new XAttribute(BCSConstants.NAME, m_identifier.Name),
                                        new XAttribute(BCSConstants.TYPENAME, m_identifier.PropertyType.FullName)
                                    )
                                )
                            )
                        )
                ),
                //METHODINSTANCES
                new XElement(m_ns + BCSConstants.METHODINSTANCES,
                //METHODINSTANCE
                    GetIdEnumeratorMethodInstance(BCSConstants.MethodType.IdEnumerator, m_idEnumeratorName, m_idCollection, false)
                )
            );
            return idEnumerator;
        }

        private XElement GetCreateMethod()
        {
            XElement createmethod = new XElement(m_ns + BCSConstants.METHOD,
                new XAttribute(BCSConstants.NAME, m_createName),

                 //PARAMETERS
                new XElement(m_ns + BCSConstants.PARAMETERS,

                    //RETURN PARAMETER
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.NAME, m_returnParameterName),
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.Return),

                        //TYPEDESCRIPTOR
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                            new XAttribute(BCSConstants.NAME, m_returnParameterName),
                                GetTypeDescriptorFromTypeProperties()
                         )
                    ),

                    //IN PARAMETER
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.NAME, m_newParameterName),
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.In),

                        //TYPEDESCRIPTOR
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                            new XAttribute(BCSConstants.NAME, m_newParameterName),
                                GetTypeDescriptorFromTypePropertiesForCreator()
                         )

                    )
                ),

                //METHODINSTANCES
                new XElement(m_ns + BCSConstants.METHODINSTANCES,

                    //METHODINSTANCE
                    GetCreateMethodInstance(BCSConstants.MethodType.Creator, m_createName, m_returnParameterName, true)
                )
            );
            return createmethod;
        }
        
        private XElement GetUpdateMethod()
        {
            XElement updatemethod = new XElement(m_ns + BCSConstants.METHOD,
                new XAttribute(BCSConstants.NAME, m_updateName),

                 //PARAMETERS
                new XElement(m_ns + BCSConstants.PARAMETERS,

                    //IN PARAMETER
                    new XElement(m_ns + BCSConstants.PARAMETER,
                        new XAttribute(BCSConstants.NAME, m_type.Name),
                        new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.In),

                        //TYPEDESCRIPTORs
                        new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                            new XAttribute(BCSConstants.TYPENAME, m_classFullName),
                            new XAttribute(BCSConstants.NAME, m_newParameterName),
                                GetTypeDescriptorFromTypePropertiesForUpdator()
                         )
                    )
                ),

                //METHODINSTANCES
                new XElement(m_ns + BCSConstants.METHODINSTANCES,

                    //METHODINSTANCE
                    GetUpdateMethodInstance(m_updateName)
                )
            );
            return updatemethod;
        }

        private XElement GetDeleteMethod()
        {
           /*
            * <Method Name="Delete">
              <Parameters>
                <Parameter Name="identifier1" Direction="In">
                  <TypeDescriptor Name="Identifier1" TypeName="System.String" IdentifierEntityName="Entity1" IdentifierEntityNamespace="BCSExample.BdcModel1" IdentifierName="Identifier1" /></Parameter>
              </Parameters>
              <MethodInstances>
                <MethodInstance Name="Delete" Type="Deleter" />
              </MethodInstances></Method>
            <!-- end specific finder method -->
          </Methods>
            * */

            XElement createmethod = new XElement(m_ns + BCSConstants.METHOD,
                            new XAttribute(BCSConstants.NAME, m_deleteName),

                             //PARAMETERS
                            new XElement(m_ns + BCSConstants.PARAMETERS,

                                //IN PARAMETER
                                new XElement(m_ns + BCSConstants.PARAMETER,
                                    new XAttribute(BCSConstants.NAME, m_identifier.Name),
                                    new XAttribute(BCSConstants.DIRECTION, BCSConstants.DIRECTIONVALUE.In),

                                    //TYPEDESCRIPTORs
                                    new XElement(m_ns + BCSConstants.TYPEDESCRIPTOR,
                                        new XAttribute(BCSConstants.NAME, m_identifier.Name),
                                        new XAttribute(BCSConstants.TYPENAME, m_identifier.PropertyType.FullName),
                                        new XAttribute(BCSConstants.IDENTIFIERENTITYNAME, m_type.Name),
                                        new XAttribute(BCSConstants.IDENTIFIERENTITYNAMESPACE, m_type.Namespace),
                                        new XAttribute(BCSConstants.IDENTIFIERNAME, m_identifier.Name)
                                     )
                                )
                            ),

                            //METHODINSTANCES
                            new XElement(m_ns + BCSConstants.METHODINSTANCES,

                                //METHODINSTANCE
                                GetDeleteMethodInstance(m_deleteName)
                            )
                        );
            return createmethod;


        }


        private XElement GetTypeDescriptorFromTypeProperties()
        {
            XElement typedescriptor = new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS);
            foreach (PropertyInfo pinfo in m_type.GetProperties())
            {
                if (m_propertyfilter.Contains(pinfo))
                {
                    typedescriptor.Add(this.GetTypeDescriptorFromTypeProperty(pinfo));
                }
            }
            return typedescriptor;
        }

        private XElement GetTypeDescriptorFromTypePropertiesForCreator()
        {
            XElement typedescriptor = new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS);
            foreach (PropertyInfo pinfo in m_type.GetProperties())
            {
                if (m_propertyfilter.Contains(pinfo))
                {
                    typedescriptor.Add(this.GetTypeDescriptorFromTypePropertyForCreator(pinfo));
                }
            }
            return typedescriptor;
        }

        private XElement GetTypeDescriptorFromTypePropertiesForUpdator()
        {
            XElement typedescriptor = new XElement(m_ns + BCSConstants.TYPEDESCRIPTORS);
            foreach (PropertyInfo pinfo in m_type.GetProperties())
            {
                if (m_propertyfilter.Contains(pinfo))
                {
                    typedescriptor.Add(this.GetTypeDescriptorFromTypePropertyForUpdator(pinfo));
                }
            }
            return typedescriptor;
        }

        private XElement GetTypeDescriptorFromTypeProperty(PropertyInfo property)
        {
            XElement typedesc = new XElement(
                m_ns + BCSConstants.TYPEDESCRIPTOR,
                new XAttribute(BCSConstants.NAME, property.Name),
                new XAttribute(BCSConstants.TYPENAME, property.PropertyType.FullName)
                );

            if (property.Name == m_identifier.Name)
            {
                typedesc.Add(
                    new XAttribute(BCSConstants.IDENTIFIERNAME, property.Name),
                    new XAttribute(BCSConstants.READONLY, true)
                    );
            }

            return typedesc;
        }

        private XElement GetTypeDescriptorFromTypePropertyForCreator(PropertyInfo property)
        {

            XElement typedesc = new XElement(
                m_ns + BCSConstants.TYPEDESCRIPTOR,
                new XAttribute(BCSConstants.NAME, property.Name),
                new XAttribute(BCSConstants.TYPENAME, property.PropertyType.FullName),
                new XAttribute(BCSConstants.CREATORFIELD, true)
                );

            if (property.Name == m_identifier.Name)
            {
                typedesc.Add(
                    new XAttribute(BCSConstants.IDENTIFIERNAME, property.Name)
                    );
            }

            return typedesc;
        }

        private XElement GetTypeDescriptorFromTypePropertyForUpdator(PropertyInfo property)
        {
            //<TypeDescriptor Name="Id" TypeName="System.String" IdentifierName="Id" />
            XElement typedesc = new XElement(
                m_ns + BCSConstants.TYPEDESCRIPTOR,
                new XAttribute(BCSConstants.NAME, property.Name),
                new XAttribute(BCSConstants.TYPENAME, property.PropertyType.FullName),
                new XAttribute(BCSConstants.UPDATERFIELD, true)
                );

            if (property.Name == m_identifier.Name)
            {
                typedesc.Add(
                    new XAttribute(BCSConstants.IDENTIFIERNAME, property.Name)
                    );
            }

            return typedesc;
        }


        private XElement GetFinderMethodInstance(BCSConstants.MethodType type, string methodname, string displayname, bool isDefault)
        {
            //FINDER & SPECIFICFINDER
            if (type == BCSConstants.MethodType.SpecificFinder || type == BCSConstants.MethodType.Finder)
            {
                return new XElement(m_ns + BCSConstants.METHODINSTANCE,
                                        new XAttribute(BCSConstants.TYPE, type),
                                        new XAttribute(BCSConstants.RETURNPARAMETERNAME, m_returnParameterName),
                                        new XAttribute(BCSConstants.DEFAULT, isDefault),
                                        new XAttribute(BCSConstants.NAME, methodname),
                                        new XAttribute(BCSConstants.DEFAULTDISPLAYNAME, displayname)
                                    );
            }
            else
            {
                throw new InvalidOperationException("This type '" + type + "' is not supported for this method ");
            }

        }

        private XElement GetIdEnumeratorMethodInstance(BCSConstants.MethodType type, string methodname, string returntypedescriptorpath, bool isDefault)
        {
            if (type == BCSConstants.MethodType.IdEnumerator)
            {
                return new XElement(m_ns + BCSConstants.METHODINSTANCE,
                                        new XAttribute(BCSConstants.TYPE, type),
                                        new XAttribute(BCSConstants.RETURNPARAMETERNAME, m_returnParameterName),
                                        new XAttribute(BCSConstants.NAME, methodname),
                                        new XAttribute(BCSConstants.RETURNTYPEDESCRIPTORPATH, returntypedescriptorpath)
                                     );
            }

            else
            {
                throw new InvalidOperationException("This type '" + type + "' is not supported for this method ");
            }

        }

        private XElement GetCreateMethodInstance(BCSConstants.MethodType type, string name, string returntypedescriptorpath, bool isDefault)
        {

            //CREATOR
            if (type == BCSConstants.MethodType.Creator)
            {
                return new XElement(m_ns + BCSConstants.METHODINSTANCE,
                                        new XAttribute(BCSConstants.TYPE, type),
                                        new XAttribute(BCSConstants.RETURNPARAMETERNAME, m_returnParameterName),
                                        new XAttribute(BCSConstants.NAME, name),
                                        new XAttribute(BCSConstants.RETURNTYPEDESCRIPTORPATH, m_returnParameterName)
                                    );
            }else
            {
                throw new InvalidOperationException("This type '" + type + "' is not supported for this method ");
            }

        }

        private XElement GetUpdateMethodInstance(string name)
        {
            return new XElement(m_ns + BCSConstants.METHODINSTANCE,
                                        new XAttribute(BCSConstants.TYPE, BCSConstants.MethodType.Updater),
                                        new XAttribute(BCSConstants.NAME, name)
                                    );
        }

        private XElement GetDeleteMethodInstance(string m_deleteName)
        {
            return new XElement(m_ns + BCSConstants.METHODINSTANCE,
                                        new XAttribute(BCSConstants.TYPE, BCSConstants.MethodType.Deleter),
                                        new XAttribute(BCSConstants.NAME, m_deleteName)
                                    );
        }
    }
}